package com.zhuyuan.database.scope;

import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.zhuyuan.core.util.StringUtils;
import com.zhuyuan.security.service.UserDetailsImpl;
import com.zhuyuan.security.util.SecurityUtils;
import com.zhuyuan.system.api.domain.SysRole;
import com.zhuyuan.system.api.domain.UserInfo;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: 张琳凯
 * @Description: TODO
 * @DateTime: 2025/2/28 14:28
 **/


public class DataScopeInterceptor implements InnerInterceptor {

    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        //是否需要数据过滤
        // 检查是否存在忽略数据权限的注解
        if (hasIgnoreDataScopeAnnotation(ms)) {
            return;
        }
        // 获取原始SQL
        String originalSql = boundSql.getSql();
        // 拼接新SQL
        String buildSql = applyDataScope(originalSql);//+" where user_id=1";

        // 重写SQL
        PluginUtils.mpBoundSql(boundSql).sql(buildSql);
    }

    /**
     * 检查是否标记了忽略数据权限注解
     */
    private boolean hasIgnoreDataScopeAnnotation(MappedStatement ms) {
        try {
            String methodId = ms.getId();
            Class<?> mapperClass = Class.forName(methodId.substring(0, methodId.lastIndexOf('.')));
            Method method = mapperClass.getMethod(methodId.substring(methodId.lastIndexOf('.') + 1));
            return method.isAnnotationPresent(IgnoreDataScope.class);
        } catch (Exception e) {
            return false;
        }
    }

    private String applyDataScope(String sql) {
        //当前用户
        UserDetailsImpl currentUser = SecurityUtils.getCurrentUser();
        //如果是管理员或者允许匿名访问的，则不进行数据过滤
        if (currentUser == null || currentUser.getUserInfo().isAdmin()) {
            return sql;
        }
        UserInfo userInfo = currentUser.getUserInfo();
        // 获取最终数据权限类型（处理多角色优先级）
        DataScopeType finalScope = resolveDataScopeType(userInfo.getRoles());
        String condition = buildCondition(finalScope,userInfo);
        if (StringUtils.isEmpty(condition)) {
            return sql;
        }
        // 智能拼接WHERE/AND（避免重复WHERE）
        return appendConditionToSql(sql, condition);
    }
    /**
     * 解析多角色的最终数据权限（优先级：ALL > CUSTOM > DEPT_AND_BELOW > DEPT > SELF）
     */
    private DataScopeType resolveDataScopeType(List<SysRole> roles) {
        if (roles == null || roles.isEmpty()) {
            return DataScopeType.SELF; // 默认最低权限
        }

        // 按优先级排序后的权限列表
        List<DataScopeType> orderedScopes = roles.stream()
                .map(r -> DataScopeType.parse(r.getDataScope()))
                .sorted(Comparator.comparingInt(DataScopeType::getPriority))
                .collect(Collectors.toList());

        // 返回优先级最高的权限
        return orderedScopes.get(0);
    }

    /**
     * 根据权限类型构建条件
     */
    private String buildCondition(DataScopeType scopeType, UserInfo userInfo) {
        switch (scopeType) {
            case ALL:
                return "1=1"; // 无限制
            case CUSTOM:
                List<String> roleIds = userInfo.getRoleIds();
                return "dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in ("+org.springframework.util.StringUtils.collectionToCommaDelimitedString(roleIds)+") ) ";
            case DEPT_AND_BELOW:
                List<Long> deptIds = userInfo.getDeptAndSubIds();
                return "dept_id IN (" + org.springframework.util.StringUtils.collectionToCommaDelimitedString(deptIds) + ")";
            case DEPT:
                return "dept_id = " + userInfo.getUser().getDeptId();
            case SELF:
                return "user_id = " + userInfo.getUser().getUserId();
            default:
                throw new IllegalArgumentException("未知数据权限类型");
        }
    }
    /**
     * 智能拼接SQL条件（处理原始SQL是否包含WHERE）
     */
    private String appendConditionToSql(String originalSql, String condition) {
        String upperSql = originalSql.toUpperCase();
        if (upperSql.contains("WHERE")) {
            return originalSql + " AND " + condition;
        } else {
            return originalSql + " WHERE " + condition;
        }
    }

}